package com.jsy.common.util.m3u8.downloadAndPlayer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * M3U8 下载器
 */
public class M3U8Downloader {
    private static final int CONNECT_TIMEOUT = 10000;
    private static final int READ_TIMEOUT = 30000;
    private static final int DOWNLOAD_THREADS = 10;
    
    private String m3u8Url;
    private String saveDir;
    private String baseUrl;
    private List<String> tsUrls = new ArrayList<>();
    private ExecutorService threadPool;
    private AtomicInteger downloadedCount = new AtomicInteger(0);
    private int totalCount = 0;

    public M3U8Downloader(String m3u8Url, String saveDir) {
        this.m3u8Url = m3u8Url;
        this.saveDir = saveDir;
        this.baseUrl = extractBaseUrl(m3u8Url);
        this.threadPool = Executors.newFixedThreadPool(DOWNLOAD_THREADS);
    }

    /**
     * 开始下载
     */
    public void startDownload() throws IOException {
        System.out.println("开始解析M3U8文件: " + m3u8Url);
        parseM3U8(m3u8Url);
        System.out.println("解析完成，共有 " + tsUrls.size() + " 个片段需要下载");
        
        File dir = new File(saveDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        
        totalCount = tsUrls.size();
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < tsUrls.size(); i++) {
            final int index = i;
            threadPool.execute(() -> {
                try {
                    downloadTsFile(tsUrls.get(index), index);
                    int count = downloadedCount.incrementAndGet();
                    printProgress(count, totalCount, startTime);
                } catch (Exception e) {
                    System.err.println("下载片段 " + index + " 失败: " + e.getMessage());
                }
            });
        }
        
        threadPool.shutdown();
        while (!threadPool.isTerminated()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        System.out.println("\n下载完成！文件保存在: " + saveDir);
        mergeTsFiles();
    }

    /**
     * 解析M3U8文件
     */
    private void parseM3U8(String url) throws IOException {
        URL m3u8UrlObj = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) m3u8UrlObj.openConnection();
        connection.setConnectTimeout(CONNECT_TIMEOUT);
        connection.setReadTimeout(READ_TIMEOUT);
        
        try (InputStream is = connection.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
            
            String line;
            boolean isMasterPlaylist = false;
            List<String> subPlaylists = new ArrayList<>();
            
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                
                if (line.startsWith("#EXT-X-STREAM-INF")) {
                    isMasterPlaylist = true;
                    continue;
                }
                
                if (isMasterPlaylist && !line.startsWith("#")) {
                    String subUrl = resolveUrl(line);
                    subPlaylists.add(subUrl);
                    isMasterPlaylist = false;
                }
                
                if (line.startsWith("#EXTINF") || line.startsWith("#EXT-X-I-FRAME-STREAM-INF")) {
                    continue;
                }
                
                if (!line.startsWith("#") && !line.isEmpty()) {
                    String tsUrl = resolveUrl(line);
                    tsUrls.add(tsUrl);
                }
            }
            
            // 如果是主播放列表，递归解析子播放列表
            if (!subPlaylists.isEmpty()) {
                tsUrls.clear();
                for (String subUrl : subPlaylists) {
                    parseM3U8(subUrl);
                }
            }
        }
    }

    /**
     * 下载TS文件
     */
    private void downloadTsFile(String tsUrl, int index) throws IOException {
        String fileName = String.format("%05d.ts", index);
        File outputFile = new File(saveDir, fileName);
        
        URL url = new URL(tsUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(CONNECT_TIMEOUT);
        connection.setReadTimeout(READ_TIMEOUT);
        
        try (InputStream is = connection.getInputStream();
             FileOutputStream fos = new FileOutputStream(outputFile)) {
            
            ReadableByteChannel rbc = Channels.newChannel(is);
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        }
    }

    /**
     * 合并TS文件
     */
    private void mergeTsFiles() {
        System.out.println("开始合并TS文件...");
        try {
            File outputFile = new File(saveDir, "output.ts");
            try (FileOutputStream fos = new FileOutputStream(outputFile)) {
                
                for (int i = 0; i < totalCount; i++) {
                    String fileName = String.format("%05d.ts", i);
                    File tsFile = new File(saveDir, fileName);
                    
                    if (tsFile.exists()) {
                        Files.copy(tsFile.toPath(), fos);
                        // 合并后删除单个TS文件，节省空间
                        // tsFile.delete();
                    }
                }
            }
            System.out.println("合并完成！输出文件: " + outputFile.getAbsolutePath());
        } catch (Exception e) {
            System.err.println("合并文件失败: " + e.getMessage());
        }
    }

    /**
     * 解析基础URL
     */
    private String extractBaseUrl(String url) {
        int lastSlashIndex = url.lastIndexOf('/');
        if (lastSlashIndex > 0) {
            return url.substring(0, lastSlashIndex + 1);
        }
        return url;
    }

    /**
     * 解析完整URL
     */
    private String resolveUrl(String path) {
        if (path.startsWith("http")) {
            return path;
        } else if (path.startsWith("/")) {
            // 绝对路径
            Pattern pattern = Pattern.compile("(https?://[^/]+)");
            Matcher matcher = pattern.matcher(baseUrl);
            if (matcher.find()) {
                return matcher.group(1) + path;
            }
        }
        // 相对路径
        return baseUrl + path;
    }

    /**
     * 打印下载进度
     */
    private void printProgress(int current, int total, long startTime) {
        long elapsedTime = System.currentTimeMillis() - startTime;
        double speed = (double) current * 1000 / (elapsedTime + 1); // 每秒下载的文件数
        int percent = (int) ((double) current / total * 100);
        
        StringBuilder progressBar = new StringBuilder();
        progressBar.append("[");
        int barWidth = 50;
        int filledWidth = (int) (barWidth * percent / 100);
        for (int i = 0; i < barWidth; i++) {
            progressBar.append(i < filledWidth ? "=" : " ");
        }
        progressBar.append("] ");
        progressBar.append(String.format("%d%% (%d/%d) ", percent, current, total));
        progressBar.append(String.format("%.2f 片段/秒", speed));
        
        // 使用\r回到行首，实现进度条动态更新
        System.out.print("\r" + progressBar.toString());
    }
}    